﻿#include "qbindtcpsocket.h"

#include <QHostAddress>

QBindTcpSocket::QBindTcpSocket(QObject *parent):
    QTcpSocket(parent)
{

}

QBindTcpSocket::~QBindTcpSocket()
{

}

int QBindTcpSocket::bindAddrAndPort(QString localAddr, quint16 localPort)
{
    QString str = localAddr;
    QHostAddress addr(str);
    setLocalAddress(addr);
    setLocalPort(localPort);
    return 0;
}

//-------------------------------
TcpConnectDetect::TcpConnectDetect(QObject *parent) :
    QObject(parent),
    m_pDetectSocket(NULL),
    m_localip(DEF_LOCAL_IP),
    m_localport(DEF_LOCAL_PORT),
    m_serverip(DEF_SERVER_IP),
    m_serverport(DEF_SERVER_PORT)
{
}

TcpConnectDetect::~TcpConnectDetect()
{
    if (m_pDetectSocket == NULL)
    {
        m_pDetectSocket->disconnectFromHost();
        m_pDetectSocket->waitForDisconnected();
        m_pDetectSocket->close();
        delete m_pDetectSocket;
    }
}

void TcpConnectDetect::detectStart()
{
    qDebug("TcpConnectDetect start");
    if (m_pDetectSocket == NULL)
    {
        m_pDetectSocket = new QBindTcpSocket;
    }
}

int TcpConnectDetect::connectDetect()
{
    int connectsta = 0;
    int rslt;

 //   qDebug() << "TcpConnectDetect " << QThread::currentThread();

    if (m_pDetectSocket == NULL)
    {
        return 0;
    }
    if (m_localip.isEmpty() == false)
    {
        m_pDetectSocket->bindAddrAndPort(m_localip, m_localport);
    }
    m_pDetectSocket->abort();
    m_pDetectSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
    m_pDetectSocket->connectToHost(m_serverip, m_serverport);

    do
    {
        rslt = m_pDetectSocket->waitForConnected(4000);     // 等待连接

        qDebug("bind Detect connect rslt=%d", rslt);
        qDebug() << "localip=" << m_localip << "localport=" << m_localport;
        qDebug() << "serverip=" << m_serverip << "serverport=" << m_serverport;

        switch(m_pDetectSocket->state())
        {
        case QAbstractSocket::ConnectedState:
        {
            // 如果连接上，说明 m_pClientSocket 连接已经无效, 需要断开重新连接
            // 先断开测试连接
            m_pDetectSocket->disconnectFromHost();
            m_pDetectSocket->waitForDisconnected();
            connectsta = 1;
            // 发送断开主连接的信号
            qDebug() << "detect is Connected, disconnect all";

            break;
        }
        case QAbstractSocket::UnconnectedState:
        {
        //    qDebug() << "detect is Unconnected err=" << m_pDetectSocket->error() << ", info:" << m_pDetectSocket->errorString();

            switch (m_pDetectSocket->error())
            {
               case QAbstractSocket::SocketTimeoutError:      // 连接超时，说明已经断开
               case QAbstractSocket::NetworkError:            // 网络错误, 主机不可连接, 可能已经断开
               {
                    qDebug() << "detect is timout, disconnect all";
                    connectsta = 1;
                    // 发送断开主连接的信号
                    break;
               }
               case QAbstractSocket::ConnectionRefusedError:  // 拒绝连接, 说明连接还在
               {
                   connectsta = 2;
               //    qDebug() << "Connection Refused, old connect is alive";
                   break;
               }
                /*
                    case QAbstractSocket::RemoteHostClosedError:
                    case QAbstractSocket::HostNotFoundError:
                    case QAbstractSocket::SocketAccessError:
                    case QAbstractSocket::SocketResourceError:
                    case QAbstractSocket::SocketTimeoutError:
                    case QAbstractSocket::DatagramTooLargeError:
                    case QAbstractSocket::AddressInUseError:
                    case QAbstractSocket::SocketAddressNotAvailableError:
                    case QAbstractSocket::UnsupportedSocketOperationError:
                    case QAbstractSocket::UnfinishedSocketOperationError:
                    case QAbstractSocket::ProxyAuthenticationRequiredError:
                    case QAbstractSocket::SslHandshakeFailedError:
                    case QAbstractSocket::ProxyConnectionRefusedError:
                    case QAbstractSocket::ProxyConnectionClosedError:
                    case QAbstractSocket::ProxyConnectionTimeoutError:
                    case QAbstractSocket::ProxyNotFoundError:
                    case QAbstractSocket::ProxyProtocolError:
                    case QAbstractSocket::UnknownSocketError:
                    */
               default:
               {
                   // 继续检测
                   connectsta = 2;
                   qDebug() << " retry";
                   break;
               }
            }   // 错误处理结束
        }
        case QAbstractSocket::ConnectingState:
        {
         //   qDebug() << "detect is Connecting";
            //   qDebug() << "localip=" << m_localip << "localport=" << m_localport;
            // 继续等待
            break;
        }
        case QAbstractSocket::HostLookupState:
        case QAbstractSocket::BoundState:
        case QAbstractSocket::ListeningState:
        case QAbstractSocket::ClosingState:
        default:
        {
            // 继续等待
            qDebug("detect sta is %d\r\n", m_pDetectSocket->state());
            break;
        }
        }

        if (connectsta != 0)
        {
            break;
        }

    }while(1);


    m_pDetectSocket->close();

    // 发送本次测试连接的状态信号
    emit(siConnectSta(connectsta));
    return connectsta;
}

void TcpConnectDetect::setIpAndPort(QString localip, quint16 localport, QString serverip, quint16 serverport)
{
    m_localip    = localip;
    m_localport  = localport;
    m_serverip   = serverip;
    m_serverport = serverport;
}
